home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
os2
/
plnk081.zip
/
pilot-link.0.8.1
/
libsock
/
os2serial.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-11
|
11KB
|
393 lines
/* os2serial.c: tty line interface code for Pilot comms under OS/2
*
* Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski.
* This is free software, licensed under the GNU Public License V2.
* See the file COPYING for details.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <io.h>
#include "pi-source.h"
#include "pi-socket.h"
#include "pi-serial.h"
#include "pi-slp.h"
#include "pi-syspkt.h"
#include "pi-padp.h"
#ifdef HAVE_SYS_IOCTL_COMPAT_H
#include <sys/ioctl_compat.h>
#endif
#define INCL_BASE
#define INCL_DOSFILEMGR /* File System values */
#define INCL_DOSDEVIOCTL /* DosDevIOCtl values */
#define INCL_DOSDEVICES /* DosDevice values */
#include <os2.h>
static int so_changebaud(struct pi_socket *ps);
static int so_close(struct pi_socket *ps);
static int pi_socket_set_timeout(struct pi_socket *ps, int read_timeout,
int write_timeout);
static int so_write(struct pi_socket *ps);
static int so_read(struct pi_socket *ps, int timeout);
int pi_serial_open(struct pi_socket *ps, struct pi_sockaddr * addr, int addrlen)
{
int rc;
HFILE fd;
unsigned long action;
int filesize=0;
char * tty = addr->pi_device;
if ((!tty) || !strlen(tty))
tty = getenv("PILOTPORT");
if (!tty)
tty = "<Null>";
/* open the device */
rc=DosOpen(tty, /* the device */
&fd, /* the file descriptor returned */
&action, /* the action taken */
filesize, /* the size of the file */
FILE_NORMAL, /* file permissions mode, not the same as UNIX */
OPEN_ACTION_OPEN_IF_EXISTS, /* file open action */
OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, /* open mode */
0); /* extended attributes */
if (rc)
{
switch (rc)
{
case 2: /* ERROR_FILE_NOT_FOUND */
errno=ENOENT;
break;
case 3: /* ERROR_PATH_NOT_FOUND */
errno=ENOTDIR;
break;
case 4: /* ERROR_TOO_MANY_OPEN_FILES */
errno=EMFILE;
break;
case 5: /* ERROR_ACCESS_DENIED */
errno=EACCES;
break;
case 32: /* ERROR_SHARING_VIOLATION */
errno=EBUSY;
break;
case 82: /* ERROR_CANNOT_MAKE */
errno=EEXIST;
break;
case 99: /* ERROR_DEVICE_IN_USE */
errno=EBUSY;
break;
case 112: /* ERROR_DISK_FULL */
errno=ENOSPC;
break;
case 87: /* ERROR_INVALID_PARAMETER */
errno=EINVAL;
break;
default:
errno=-ENOMSG;
break;
}
return(-1);
}
ps->mac->fd=_imphandle(fd); /* Let EMX know about this handle */
ps->mac->fd=dup2(ps->mac->fd, ps->sd); /* Substitute serial connection for
original NUL handle */
ps->serial_changebaud = so_changebaud;
so_changebaud(ps);
pi_socket_set_timeout(ps,-1,600);
ps->serial_close = so_close;
ps->serial_read = so_read;
ps->serial_write = so_write;
#ifndef NO_SERIAL_TRACE
if (ps->debuglog) {
ps->debugfd = open(ps->debuglog,O_WRONLY|O_CREAT,0666);
/* This sequence is magic used by my trace analyzer - kja */
write(ps->debugfd, "\0\1\0\0\0\0\0\0\0\0", 10);
}
#endif
return(fd);
}
static int so_changebaud(struct pi_socket *ps)
{
int param_length;
int rc, baudrate;
unsigned char linctrl[3] = {8,0,0};
baudrate = ps->rate;
param_length=sizeof(baudrate);
rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
IOCTL_ASYNC, /*asyncronous change */
ASYNC_SETBAUDRATE, /* set the baudrate */
&baudrate, /* pointer to the baudrate */
param_length, /* length of the previous parameter */
(unsigned long *)¶m_length, /* max length of data ret */
NULL, /* data to be sent */
0, /* length of data */
NULL); /* length of data returned */
/* also set the port to 8N1 as OS/2 defaults to some braindead values */
if (!rc) /* but only if the previous operation succeeded */
{
param_length = 3; /* 3 bytes for line control */
rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
IOCTL_ASYNC, /*asyncronous change */
ASYNC_SETLINECTRL, /* set the line controls */
linctrl, /* pointer to the configuration */
param_length, /* length of the previous parameter */
(unsigned long *)¶m_length, /* max length of params */
NULL, /* data to be returned */
0, /* length of data */
NULL); /* length of data returned */
}
if (rc)
{
switch (rc)
{
case 1: /* ERROR_INVALID_FUNCTION */
errno=ENOTTY;
break;
case 6: /* ERROR_INVALID_HANDLE */
errno=EBADF;
break;
case 87: /* ERROR_INVALID_PARAMETER */
errno=EINVAL;
break;
default:
errno=-ENOMSG;
break;
}
return(-1);
}
/* this pause seems necessary under OS2 to let the serial
port realign itself */
sleep(1);
#ifdef OS2_DEBUG
fprintf(stderr,"set baudrate to %d\n",baudrate);
#endif
return(0);
}
static int so_close(struct pi_socket *ps)
{
#ifndef NO_SERIAL_TRACE
if (ps->debugfd)
close(ps->debugfd);
#endif
DosClose(ps->mac->fd);
return(0);
}
/*
* values for read_timeout and write_timeout
* 0 = infinite timeout
* 1 to 65535 = timeout in seconds
* -1 = dont change timeout
*/
static int pi_socket_set_timeout(struct pi_socket *ps, int read_timeout,
int write_timeout)
{
int param_length, ret_len;
int rc;
int newtimeout;
DCBINFO devinfo;
if ((ps->os2_read_timeout==read_timeout || read_timeout==-1) &&
(ps->os2_write_timeout==write_timeout || write_timeout==-1))
return(0);
ret_len=sizeof(DCBINFO);
rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
IOCTL_ASYNC, /*asyncronous change */
ASYNC_GETDCBINFO, /* get device control block info */
NULL, /* */
0, /* length of the previous parameter */
NULL, /* max length of data ret */
&devinfo, /* data to be recieved */
ret_len, /* length of data */
(unsigned long *)&ret_len); /* length of data returned */
if (rc)
goto error;
if (read_timeout!=-1)
{
if (read_timeout==0)
{
devinfo.usReadTimeout=65535;
}
else
{
newtimeout=read_timeout -0.1;
if (newtimeout>65535)
newtimeout=65535;
devinfo.usReadTimeout=newtimeout;
}
}
if (write_timeout==-1)
{
if (write_timeout==0)
{
devinfo.fbTimeout |=0x01;
}
else
{
devinfo.fbTimeout &= 0xFE;
newtimeout=write_timeout;
if (newtimeout>65535)
newtimeout=65535;
devinfo.usWriteTimeout=newtimeout;
}
}
param_length=sizeof(DCBINFO);
rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
IOCTL_ASYNC, /*asyncronous change */
ASYNC_SETDCBINFO, /* get device control block info */
&devinfo, /* parameters to set */
param_length, /* length of the previous parameter */
(unsigned long *)¶m_length, /* max length of parameters */
NULL, /* data to be recieved */
0, /* length of data */
NULL); /* length of data returned */
error:
if (rc)
{
switch (rc)
{
case 1: /* ERROR_INVALID_FUNCTION */
errno=ENOTTY;
break;
case 6: /* ERROR_INVALID_HANDLE */
errno=EBADF;
break;
case 87: /* ERROR_INVALID_PARAMETER */
errno=EINVAL;
break;
default:
errno=-ENOMSG;
break;
}
return(-1);
}
if (read_timeout!=-1)
ps->os2_read_timeout=read_timeout;
if (write_timeout!=-1)
ps->os2_write_timeout=write_timeout;
#ifdef OS2_DEBUG
// fprintf(stderr,"set read_timeout to %d\n",read_timeout);
// fprintf(stderr,"set write_timeout to %d\n",write_timeout);
#endif
return(0);
}
static int so_write(struct pi_socket *ps)
{
struct pi_skb *skb;
int nwrote, len;
#ifndef NO_SERIAL_TRACE
int i;
#endif
int rc;
if (ps->txq) {
ps->busy++;
skb = ps->txq;
ps->txq = skb->next;
len = 0;
while (len<skb->len) {
nwrote = 0;
rc=DosWrite(ps->mac->fd,skb->data,skb->len,(unsigned long *)&nwrote);
if (nwrote<=0)
break; /* transmission failure */
len += nwrote;
}
#ifndef NO_SERIAL_TRACE
if (ps->debuglog)
for (i=0;i<skb->len;i++) {
write(ps->debugfd, "2", 1);
write(ps->debugfd, skb->data+i, 1);
}
#endif
ps->tx_bytes += skb->len;
free(skb);
ps->busy--;
return 1;
}
return 0;
}
static int so_read(struct pi_socket *ps, int timeout)
{
int r;
unsigned char *buf;
#ifndef NO_SERIAL_TRACE
int i;
#endif
int rc;
/* FIXME: if timeout == 0, wait forever for packet, otherwise wait till
timeout tenth-of-seconds */
/* for OS2, timeout of 0 is almost forever, only 1.8 hours */
/* if no timeout is set at all, the timeout defaults to 1 minute */
rc=pi_socket_set_timeout(ps,timeout,-1);
if (rc==-1)
{
fprintf(stderr,"error setting timeout, old timeout used\n");
}
pi_serial_flush(ps); /* We likely want to be in sync with tx */
if (!ps->mac->expect) slp_rx(ps); /* let SLP know we want a packet */
while (ps->mac->expect) {
buf = ps->mac->buf;
while (ps->mac->expect) {
rc=DosRead(ps->mac->fd,buf,ps->mac->expect,(unsigned long *)&r);
if (rc)
{
/* otherwise throw out any current packet and return */
#ifdef DEBUG
fprintf(stderr, "Serial RX: timeout\n");
#endif
ps->mac->state = ps->mac->expect = 1;
ps->mac->buf = ps->mac->rxb->data;
ps->rx_errors++;
return 0;
}
#ifndef NO_SERIAL_TRACE
if (ps->debuglog)
for (i=0;i<r;i++) {
write(ps->debugfd, "1", 1);
write(ps->debugfd, buf+i, 1);
}
#endif
ps->rx_bytes += r;
buf += r;
ps->mac->expect -= r;
}
slp_rx(ps);
}
return 0;
}